Load data

# Sourcing External R Script
source("https://raw.githubusercontent.com/Cassava2050/PPD/main/utilities_tidy.R")

# Setting Up File Paths and Parameters
folder <- here::here("data//")  
file <- "phenotype.csv"
skip_col <- 3 
trial_interest <- "MDEPR"
year_interest <- 2022

# Loading Data
# The function 'read_cassavabase' should be defined in the sourced script
sel_data <- read_cassavabase(phenotypeFile = paste0(folder, file))
## 
## Trials interested are:
##  2023111DMF1C_dona 2023112DMF1C_tani 2023113DMEPR_dona 2023114DMEPR_tani

Standardizing Column Names

The function ‘change_colname’ should also be defined in the sourced script

sel_data_kp <- change_colname(sel_data, NA)
## [1] "Good, the column names are standardized names now!"

Changing Column type

obs_col <- c(
  names(sel_data_kp)[str_detect(names(sel_data_kp), "obs_")],
  "use_rep_number", "blockNumber",
  "use_plot_number", "use_plot_width",
  "use_plot_length"
)

mutate all traits into numeric

sel_data_kp <- sel_data_kp %>% 
  mutate(across(all_of(obs_col), as.numeric))

# remove - , replace by _
names(sel_data_kp) = gsub("-", "_", names(sel_data_kp))

# Duplications in row and cols
duplicated_plot <- row_col_dup(sel_data_kp)
## [1] "Good, there is no duplicated combination of row and column."

Plot trial layout

Check the clone name

cloneName_new_old <- check_clone_name(
  clone_list = sel_data_kp$use_accession_name,
  new_names = NA,
  add_check = NULL
)
## Released varieties: [1] "Algodona"      "Bellotti"      "Brasilera"     "Caiseli"      
##  [5] "Cantaclar04"   "Cantaclar05"   "Caribena"      "Caselli"      
##  [9] "Catumare"      "CC4-Guyana"    "CC5-Guyana"    "CG1141-1"     
## [13] "CG489-31"      "CM3306-19"     "CM3306-4"      "CM3555-6"     
## [17] "CM4843-1"      "CM4919-1"      "CM523-7"       "CM6119-5"     
## [21] "CM6438-14"     "CM6740-7"      "CM6754-8"      "CM9021-2"     
## [25] "CMB8523"       "COL1438"       "COL1522"       "COL2215"      
## [29] "COL2737"       "Colombiana"    "Costena"       "Cubana"       
## [33] "Enana"         "Enanita"       "Gines"         "GM273-57"     
## [37] "GM4034-1"      "HMC-1"         "HMC1"          "HMC1P12"      
## [41] "INTA_amarilla" "KM94"          "KU50"          "Llenerita"    
## [45] "Melua31"       "NAT31"         "Negrita"       "Orense"       
## [49] "Reina"         "Reina_wx"      "Rojita"        "Romelia"      
## [53] "Ropain"        "SGB765-2"      "SGB765-4"      "Sinuana"      
## [57] "SM1127-8"      "SM1411-5"      "SM2775-4"      "SM2792-31"    
## [61] "SMB2446-2"     "Sucrena"       "TAI"           "TAI8"         
## [65] "Venezolana"    "Vergara"       "Veronica"     
## The other known clones: [1] "13SA05"     "Azulita"    "BB1"        "BB2"        "BB3"       
##  [6] "BK"         "C19"        "C243"       "C33"        "C39"       
## [11] "C4"         "C413"       "Chirosa"    "Chocoana"   "CMB8527"   
## [16] "CR52A2"     "CR52A4"     "CR60B10"    "FalsaReina" "FALSAREINA"
## [21] "HB60"       "HLS15"      "IBA920057"  "IBA972205"  "IBA980505" 
## [26] "KM140"      "KM419"      "KM505"      "KM94"       "KU50"      
## [31] "MBUNDUMALI" "N30"        "P13"        "Rayong11"   "SAUTI"     
## [36] "TME287"     "TME3"       "TMEB419"    "UNKNOWN1"   "UNKOWN2"   
## [1] "Good, the released names were correctly used"
## [1] "Now the standard names are used. Here are the released varieties"
## [1] "KU50_is_KM94"
## [1] "The check or released clones are:"
##        newName
## 1 KU50_is_KM94
trial_standard <- sel_data_kp %>%
  left_join(cloneName_new_old,
            by = c("use_accession_name" = "accession_name_ori")
  ) %>%
  select(-use_accession_name) %>%
  rename(use_accession_name = use_accession_name.y)

Add GIS data

trial_standard <- add_GIS(trial_standard)
## [1] "The locations are:"
## [1] "Dong Nai" "Tay Ninh"
## [1] "All locations are in the database."
# Get world map data for reference
vietnam_map <- map_data("world", region = "Vietnam")

# Create a data frame with your locations
locations <- data.frame(
  Location = c("Tay Ninh", "Dong Nai"),
  Latitude = c(11.3009, 11.1432),
  Longitude = c(106.1107, 107.2742)
)

# Create a ggplot object for the map
static_map <- ggplot() +
  geom_polygon(data = vietnam_map, aes(x = long, y = lat, group = group), 
               fill = "lightgray", col = "black", linewidth = 0.03) +
  geom_point(data = locations, aes(x = Longitude, y = Latitude), size = 2, color = "red") +
  geom_text_repel(data = locations, aes(x = Longitude, y = Latitude, label = Location), 
                  size = 3) +
  geom_text(aes(x = 108.5, y = 10, label = "Author: Luis Fdo. Delgado"), size = 1.5) +
  labs(x =  "Latitude", y = "Longitude") +
  labs(title = "Locations in Vietnam", subtitle = "Tay Ninh and Dong Nai") +
  theme(plot.title = element_text(face = "bold.italic"),
        plot.subtitle = element_text(face = "italic")) +
  coord_fixed(1.3) # This sets the aspect ratio

# Display the map
print(static_map)

# ggsave(paste("images\\map", trial_interest, ".png", sep = "_"),
#        plot = static_map, units = "in", dpi = 300, width = 6, height = 5
# )

Extracting checks

Harvesting time

conducted_trials <- 
  trial_standard %>% group_by(use_trial_name, use_plant_date,use_harvest_date, use_location) %>% 
  summarise(n_gen = n_distinct(use_accession_name)) %>% 
  mutate(harvesting_time = 
           interval(ymd(use_plant_date), ymd(use_harvest_date)) %>% as.period,
         harvesting_time = paste0(harvesting_time@month, "month ", harvesting_time@day, "day")) %>% 
  ungroup()

print(conducted_trials %>% rmarkdown::paged_table())
##      use_trial_name use_plant_date use_harvest_date use_location n_gen
## 1 2023111DMF1C_dona  2023-March-02 2023-December-08     Dong Nai   324
## 2 2023112DMF1C_tani  2023-March-09 2023-December-08     Tay Ninh   218
## 3 2023113DMEPR_dona  2023-March-02 2023-December-07     Dong Nai    36
## 4 2023114DMEPR_tani  2023-March-09 2023-December-08     Tay Ninh    36
##   harvesting_time
## 1     9month 6day
## 2    8month 29day
## 3     9month 5day
## 4    8month 29day

plot plant number

plants_plot <- trial_standard %>%
  group_by(use_trial_name) %>%
  count(obs_planted_number_plot) 
print(plants_plot)
## # A tibble: 4 × 3
## # Groups:   use_trial_name [4]
##   use_trial_name    obs_planted_number_plot     n
##   <chr>                               <dbl> <int>
## 1 2023111DMF1C_dona                       4   648
## 2 2023112DMF1C_tani                       4   432
## 3 2023113DMEPR_dona                      10   108
## 4 2023114DMEPR_tani                      10   108

Frequency harvest plant number

plants_harvested <- trial_standard %>%
  group_by(use_trial_name) %>%
  count(obs_harvest_number) %>% arrange(desc(obs_harvest_number))

plants_plot %>% select(-n) %>% 
  left_join(plants_harvested %>% 
              summarise(harvested_plants = max(obs_harvest_number, na.rm = TRUE)), by = "use_trial_name")
# planted and harvested
plants_plot %>% select(-n) %>% 
  left_join(plants_harvested %>% 
              summarise(harvested_plants = max(obs_harvest_number, na.rm = TRUE)), by = "use_trial_name") %>% 
  write.table("clipboard", sep="\t", col.names = T, row.names = F)

Double check yield calculation

plants_to_harvest <- plants_harvested %>% 
  ggplot(aes(x = factor(obs_harvest_number), 
             y = n, fill = factor(obs_harvest_number))) +
  geom_col(col = 'black') +
  #scale_fill_jco() +
  #theme_xiaofei() +
  theme(axis.text.x = element_text(vjust = 1, angle = 65),
        text = element_text(size = 20),
        legend.position="top")+
  labs(x = "Harvest_plant_number", y = "Freq", fill = "Harvest_plant_number") +
  facet_wrap(~ use_trial_name)

print(plants_to_harvest)

# ggsave(paste("images\\bar", trial_interest, ".png", sep = "_"),
#        plot = plants_to_harvest, units = "in", dpi = 300, width = 9, height = 6)

Compute germination, yield, yield_starch

trial_standard <- trial_standard %>%
  mutate(obs_harvest_number_plan =
           case_when(str_detect(use_trial_name, "2023111")  ~ 4,
                     str_detect(use_trial_name, "2023112")  ~ 4,
                     str_detect(use_trial_name, "2023113")  ~ 10,
                     str_detect(use_trial_name, "2023114")  ~ 10),
         obs_germination_perc = obs_germinated_number_plot/obs_planted_number_plot * 100,
         # 2) calculate area per plant
         area_plant = (use_plot_length*use_plot_width)/obs_planted_number_plot,
         # 3) calculate the yield_v4 obs_planted_number_plot
         obs_yield_ha = ifelse(obs_yield_ha == 0, NA, obs_yield_ha),
         obs_starch_content = ifelse(obs_starch_content == 0, NA, obs_starch_content),
         obs_yield_ha_v2 = (((obs_root_weight_plot*10000)/(area_plant*obs_harvest_number_plan))/1000),
         obs_starch_yield_ha = obs_starch_content * obs_yield_ha_v2 / 100)

library(plotly)

p1 <- trial_standard %>% ggplot() +
  geom_point(aes(x = obs_yield_ha, y = obs_yield_ha_v2, color = use_plot_number), show.legend = F) +
  facet_wrap(~use_trial_name) +
  theme_xiaofei()

ggplotly(p1)
detach("package:plotly", unload = TRUE)

Is numeric all traits?

## Is numeric all traits?
is_numeric(trial_data = trial_standard)
## [1] "Good, all traits are numeric!"
# Get the tidy data
meta_info = names(trial_standard )[str_detect(names(trial_standard), "use_")]
meta_info = gsub("use_", "", meta_info)
meta_info
##  [1] "year"               "trial_name"         "trial_type"        
##  [4] "plot_width"         "plot_length"        "plant_date"        
##  [7] "harvest_date"       "location"           "accession_name_syn"
## [10] "plot_name"          "rep_number"         "plot_number"       
## [13] "row_number"         "col_number"         "check_test"        
## [16] "notes"              "accession_name"     "check_released"    
## [19] "latitude"           "longitude"          "altitude"          
## [22] "department"         "country"            "ag_zone"           
## [25] "location_short"
trial_tidy = trial_standard
names(trial_tidy)= gsub("use_", "", names(trial_standard))

# observations
trait_list = names(trial_tidy)[str_detect(names(trial_tidy), "obs_")]
trait_list = gsub("obs_", "", trait_list)
trait_list
##  [1] "branch_number"          "CBB_3mon"               "CMD_1mon"              
##  [4] "CMD_3mon"               "CMD_6mon"               "CMD_9mon"              
##  [7] "height_1st_branch"      "yield_ha"               "root_weight_plot"      
## [10] "vigor1_5"               "vigor1_5_1mon"          "lodging1_3"            
## [13] "root_number_commercial" "planted_number_plot"    "height"                
## [16] "height_wt_leaf"         "harvest_number"         "root_number"           
## [19] "germinated_number_plot" "starch_content"         "harvest_number_plan"   
## [22] "germination_perc"       "yield_ha_v2"            "starch_yield_ha"
names(trial_tidy)= gsub("obs_", "", names(trial_tidy))
trial_tidy = trial_tidy[c(meta_info, trait_list)]

Boxplots

# Boxplots and save in output folder
dev.off()
## null device 
##           1
boxplot_traits(my_dat = trial_tidy,
               trait_wanted = trait_list,
               folder = paste0(here::here("output"), "/"), 
               trial_interest)


# Grouping boxplot
trait_wanted <- trait_list
plot_bxp <- trial_tidy %>%
  pivot_longer(
    cols = all_of(trait_wanted),
    names_to = "var",
    values_to = "values"
  ) %>%
  filter(!var %in% c(
    "stake_plant", "planted_number_plot",
    "harvest_number", "root_weight_air",
    "root_weight_water", "harvest_number_plan",
    "root_rot_perc", "yield_ha_v2"
  )) %>%
  ggplot(aes(x = trial_name, y = values)) +
  facet_wrap(~var,
             ncol = 5, scales = "free_y"
  ) + 
  geom_violin(fill = "gray") +
  geom_boxplot(width = 0.2) +
  labs(x = NULL, y = NULL, title = "") +
  theme_xiaofei() +
  theme(
    axis.text.x = element_text(size = 8, vjust = 1, angle = 65),
    axis.text.y = element_text(size = 8),
    plot.title = element_text(color = "black"),
    strip.text.x = element_text(
      size = 8, face = "bold.italic")
  ) 

print(plot_bxp)

ggsave(paste0("images\\boxplot_", trial_interest, ".png"),
       plot = plot_bxp, units = "in", dpi = 300, width = 16, height = 12
)

Save the tidy data for analysis

write.csv(trial_tidy, here::here("output", paste("01_", year_interest, trial_interest,
                                                   "_tidy_data4analysis_", ".csv", sep = "")), row.names = FALSE)
LS0tDQp0aXRsZTogIlRpZHkgZGF0YSB1cCINCmF1dGhvcjogIkx1aXMgRmVybmFuZG8gRGVsZ2FkbyINCmRhdGU6ICJgciBTeXMuRGF0ZSgpYCINCm91dHB1dDogDQogIGh0bWxfZG9jdW1lbnQ6DQogICAgdG9jOiB0cnVlDQogICAgdG9jX2Zsb2F0OiB0cnVlDQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQ0KICAgIHRoZW1lOiBwYXBlcg0KICAgIGNvZGVfZm9sZGluZzogc2hvdw0KICAgIGRmX3ByaW50OiBwYWdlZA0KLS0tDQoNCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KA0KCWVjaG8gPSBUUlVFLA0KCW1lc3NhZ2UgPSBGQUxTRSwNCgl3YXJuaW5nID0gRkFMU0UNCikNCmZpZy5kaW0gPSBjKDEwLCA1KQ0KbGlicmFyeShnZ3JlcGVsKQ0KYGBgDQoNCiMgTG9hZCBkYXRhDQpgYGB7cn0NCiMgU291cmNpbmcgRXh0ZXJuYWwgUiBTY3JpcHQNCnNvdXJjZSgiaHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL0Nhc3NhdmEyMDUwL1BQRC9tYWluL3V0aWxpdGllc190aWR5LlIiKQ0KDQojIFNldHRpbmcgVXAgRmlsZSBQYXRocyBhbmQgUGFyYW1ldGVycw0KZm9sZGVyIDwtIGhlcmU6OmhlcmUoImRhdGEvLyIpICANCmZpbGUgPC0gInBoZW5vdHlwZS5jc3YiDQpza2lwX2NvbCA8LSAzIA0KdHJpYWxfaW50ZXJlc3QgPC0gIk1ERVBSIg0KeWVhcl9pbnRlcmVzdCA8LSAyMDIyDQoNCiMgTG9hZGluZyBEYXRhDQojIFRoZSBmdW5jdGlvbiAncmVhZF9jYXNzYXZhYmFzZScgc2hvdWxkIGJlIGRlZmluZWQgaW4gdGhlIHNvdXJjZWQgc2NyaXB0DQpzZWxfZGF0YSA8LSByZWFkX2Nhc3NhdmFiYXNlKHBoZW5vdHlwZUZpbGUgPSBwYXN0ZTAoZm9sZGVyLCBmaWxlKSkNCmBgYA0KDQojIFN0YW5kYXJkaXppbmcgQ29sdW1uIE5hbWVzDQpUaGUgZnVuY3Rpb24gJ2NoYW5nZV9jb2xuYW1lJyBzaG91bGQgYWxzbyBiZSBkZWZpbmVkIGluIHRoZSBzb3VyY2VkIHNjcmlwdA0KDQpgYGB7cn0NCnNlbF9kYXRhX2twIDwtIGNoYW5nZV9jb2xuYW1lKHNlbF9kYXRhLCBOQSkNCmBgYA0KIyBDaGFuZ2luZyBDb2x1bW4gdHlwZQ0KDQpgYGB7cn0NCm9ic19jb2wgPC0gYygNCiAgbmFtZXMoc2VsX2RhdGFfa3ApW3N0cl9kZXRlY3QobmFtZXMoc2VsX2RhdGFfa3ApLCAib2JzXyIpXSwNCiAgInVzZV9yZXBfbnVtYmVyIiwgImJsb2NrTnVtYmVyIiwNCiAgInVzZV9wbG90X251bWJlciIsICJ1c2VfcGxvdF93aWR0aCIsDQogICJ1c2VfcGxvdF9sZW5ndGgiDQopDQpgYGANCg0KIyBtdXRhdGUgYWxsIHRyYWl0cyBpbnRvIG51bWVyaWMNCg0KYGBge3J9DQpzZWxfZGF0YV9rcCA8LSBzZWxfZGF0YV9rcCAlPiUgDQogIG11dGF0ZShhY3Jvc3MoYWxsX29mKG9ic19jb2wpLCBhcy5udW1lcmljKSkNCg0KIyByZW1vdmUgLSAsIHJlcGxhY2UgYnkgXw0KbmFtZXMoc2VsX2RhdGFfa3ApID0gZ3N1YigiLSIsICJfIiwgbmFtZXMoc2VsX2RhdGFfa3ApKQ0KDQojIER1cGxpY2F0aW9ucyBpbiByb3cgYW5kIGNvbHMNCmR1cGxpY2F0ZWRfcGxvdCA8LSByb3dfY29sX2R1cChzZWxfZGF0YV9rcCkNCmBgYA0KIyBQbG90IHRyaWFsIGxheW91dA0KYGBge3IgZWNobz1GQUxTRX0NCnRyaWFsX2xheW91dChzZWxfZGF0YV9rcCkNCmBgYA0KDQojIENoZWNrIHRoZSBjbG9uZSBuYW1lDQoNCmBgYHtyfQ0KY2xvbmVOYW1lX25ld19vbGQgPC0gY2hlY2tfY2xvbmVfbmFtZSgNCiAgY2xvbmVfbGlzdCA9IHNlbF9kYXRhX2twJHVzZV9hY2Nlc3Npb25fbmFtZSwNCiAgbmV3X25hbWVzID0gTkEsDQogIGFkZF9jaGVjayA9IE5VTEwNCikNCg0KdHJpYWxfc3RhbmRhcmQgPC0gc2VsX2RhdGFfa3AgJT4lDQogIGxlZnRfam9pbihjbG9uZU5hbWVfbmV3X29sZCwNCiAgICAgICAgICAgIGJ5ID0gYygidXNlX2FjY2Vzc2lvbl9uYW1lIiA9ICJhY2Nlc3Npb25fbmFtZV9vcmkiKQ0KICApICU+JQ0KICBzZWxlY3QoLXVzZV9hY2Nlc3Npb25fbmFtZSkgJT4lDQogIHJlbmFtZSh1c2VfYWNjZXNzaW9uX25hbWUgPSB1c2VfYWNjZXNzaW9uX25hbWUueSkNCmBgYA0KIyBBZGQgR0lTIGRhdGENCg0KYGBge3J9DQp0cmlhbF9zdGFuZGFyZCA8LSBhZGRfR0lTKHRyaWFsX3N0YW5kYXJkKQ0KDQojIEdldCB3b3JsZCBtYXAgZGF0YSBmb3IgcmVmZXJlbmNlDQp2aWV0bmFtX21hcCA8LSBtYXBfZGF0YSgid29ybGQiLCByZWdpb24gPSAiVmlldG5hbSIpDQoNCiMgQ3JlYXRlIGEgZGF0YSBmcmFtZSB3aXRoIHlvdXIgbG9jYXRpb25zDQpsb2NhdGlvbnMgPC0gZGF0YS5mcmFtZSgNCiAgTG9jYXRpb24gPSBjKCJUYXkgTmluaCIsICJEb25nIE5haSIpLA0KICBMYXRpdHVkZSA9IGMoMTEuMzAwOSwgMTEuMTQzMiksDQogIExvbmdpdHVkZSA9IGMoMTA2LjExMDcsIDEwNy4yNzQyKQ0KKQ0KDQojIENyZWF0ZSBhIGdncGxvdCBvYmplY3QgZm9yIHRoZSBtYXANCnN0YXRpY19tYXAgPC0gZ2dwbG90KCkgKw0KICBnZW9tX3BvbHlnb24oZGF0YSA9IHZpZXRuYW1fbWFwLCBhZXMoeCA9IGxvbmcsIHkgPSBsYXQsIGdyb3VwID0gZ3JvdXApLCANCiAgICAgICAgICAgICAgIGZpbGwgPSAibGlnaHRncmF5IiwgY29sID0gImJsYWNrIiwgbGluZXdpZHRoID0gMC4wMykgKw0KICBnZW9tX3BvaW50KGRhdGEgPSBsb2NhdGlvbnMsIGFlcyh4ID0gTG9uZ2l0dWRlLCB5ID0gTGF0aXR1ZGUpLCBzaXplID0gMiwgY29sb3IgPSAicmVkIikgKw0KICBnZW9tX3RleHRfcmVwZWwoZGF0YSA9IGxvY2F0aW9ucywgYWVzKHggPSBMb25naXR1ZGUsIHkgPSBMYXRpdHVkZSwgbGFiZWwgPSBMb2NhdGlvbiksIA0KICAgICAgICAgICAgICAgICAgc2l6ZSA9IDMpICsNCiAgZ2VvbV90ZXh0KGFlcyh4ID0gMTA4LjUsIHkgPSAxMCwgbGFiZWwgPSAiQXV0aG9yOiBMdWlzIEZkby4gRGVsZ2FkbyIpLCBzaXplID0gMS41KSArDQogIGxhYnMoeCA9ICAiTGF0aXR1ZGUiLCB5ID0gIkxvbmdpdHVkZSIpICsNCiAgbGFicyh0aXRsZSA9ICJMb2NhdGlvbnMgaW4gVmlldG5hbSIsIHN1YnRpdGxlID0gIlRheSBOaW5oIGFuZCBEb25nIE5haSIpICsNCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQuaXRhbGljIiksDQogICAgICAgIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJpdGFsaWMiKSkgKw0KICBjb29yZF9maXhlZCgxLjMpICMgVGhpcyBzZXRzIHRoZSBhc3BlY3QgcmF0aW8NCg0KIyBEaXNwbGF5IHRoZSBtYXANCnByaW50KHN0YXRpY19tYXApDQoNCiMgZ2dzYXZlKHBhc3RlKCJpbWFnZXNcXG1hcCIsIHRyaWFsX2ludGVyZXN0LCAiLnBuZyIsIHNlcCA9ICJfIiksDQojICAgICAgICBwbG90ID0gc3RhdGljX21hcCwgdW5pdHMgPSAiaW4iLCBkcGkgPSAzMDAsIHdpZHRoID0gNiwgaGVpZ2h0ID0gNQ0KIyApDQoNCmBgYA0KIyBFeHRyYWN0aW5nIGNoZWNrcw0KDQpgYGB7ciBpbmNsdWRlPUZBTFNFfQ0KYWNjZXNzaW9uX3JlcF9jdCA8LSB0cmlhbF9zdGFuZGFyZCAlPiUNCiAgY291bnQodXNlX3RyaWFsX25hbWUsIHVzZV9hY2Nlc3Npb25fbmFtZSwgdXNlX3JlcF9udW1iZXIpICAlPiUNCiAgYXJyYW5nZSh1c2VfdHJpYWxfbmFtZSkgDQogICMgZmlsdGVyKG4+MSkNCnByaW50KGFjY2Vzc2lvbl9yZXBfY3QpDQpgYGANCg0KIyBIYXJ2ZXN0aW5nIHRpbWUNCg0KYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCmNvbmR1Y3RlZF90cmlhbHMgPC0gDQogIHRyaWFsX3N0YW5kYXJkICU+JSBncm91cF9ieSh1c2VfdHJpYWxfbmFtZSwgdXNlX3BsYW50X2RhdGUsdXNlX2hhcnZlc3RfZGF0ZSwgdXNlX2xvY2F0aW9uKSAlPiUgDQogIHN1bW1hcmlzZShuX2dlbiA9IG5fZGlzdGluY3QodXNlX2FjY2Vzc2lvbl9uYW1lKSkgJT4lIA0KICBtdXRhdGUoaGFydmVzdGluZ190aW1lID0gDQogICAgICAgICAgIGludGVydmFsKHltZCh1c2VfcGxhbnRfZGF0ZSksIHltZCh1c2VfaGFydmVzdF9kYXRlKSkgJT4lIGFzLnBlcmlvZCwNCiAgICAgICAgIGhhcnZlc3RpbmdfdGltZSA9IHBhc3RlMChoYXJ2ZXN0aW5nX3RpbWVAbW9udGgsICJtb250aCAiLCBoYXJ2ZXN0aW5nX3RpbWVAZGF5LCAiZGF5IikpICU+JSANCiAgdW5ncm91cCgpDQoNCnByaW50KGNvbmR1Y3RlZF90cmlhbHMgJT4lIHJtYXJrZG93bjo6cGFnZWRfdGFibGUoKSkNCmBgYA0KIyBwbG90IHBsYW50IG51bWJlcg0KDQpgYGB7cn0NCnBsYW50c19wbG90IDwtIHRyaWFsX3N0YW5kYXJkICU+JQ0KICBncm91cF9ieSh1c2VfdHJpYWxfbmFtZSkgJT4lDQogIGNvdW50KG9ic19wbGFudGVkX251bWJlcl9wbG90KSANCnByaW50KHBsYW50c19wbG90KQ0KYGBgDQoNCiMgRnJlcXVlbmN5IGhhcnZlc3QgcGxhbnQgbnVtYmVyDQoNCmBgYHtyfQ0KcGxhbnRzX2hhcnZlc3RlZCA8LSB0cmlhbF9zdGFuZGFyZCAlPiUNCiAgZ3JvdXBfYnkodXNlX3RyaWFsX25hbWUpICU+JQ0KICBjb3VudChvYnNfaGFydmVzdF9udW1iZXIpICU+JSBhcnJhbmdlKGRlc2Mob2JzX2hhcnZlc3RfbnVtYmVyKSkNCg0KcGxhbnRzX3Bsb3QgJT4lIHNlbGVjdCgtbikgJT4lIA0KICBsZWZ0X2pvaW4ocGxhbnRzX2hhcnZlc3RlZCAlPiUgDQogICAgICAgICAgICAgIHN1bW1hcmlzZShoYXJ2ZXN0ZWRfcGxhbnRzID0gbWF4KG9ic19oYXJ2ZXN0X251bWJlciwgbmEucm0gPSBUUlVFKSksIGJ5ID0gInVzZV90cmlhbF9uYW1lIikNCg0KIyBwbGFudGVkIGFuZCBoYXJ2ZXN0ZWQNCnBsYW50c19wbG90ICU+JSBzZWxlY3QoLW4pICU+JSANCiAgbGVmdF9qb2luKHBsYW50c19oYXJ2ZXN0ZWQgJT4lIA0KICAgICAgICAgICAgICBzdW1tYXJpc2UoaGFydmVzdGVkX3BsYW50cyA9IG1heChvYnNfaGFydmVzdF9udW1iZXIsIG5hLnJtID0gVFJVRSkpLCBieSA9ICJ1c2VfdHJpYWxfbmFtZSIpICU+JSANCiAgd3JpdGUudGFibGUoImNsaXBib2FyZCIsIHNlcD0iXHQiLCBjb2wubmFtZXMgPSBULCByb3cubmFtZXMgPSBGKQ0KYGBgDQoNCiMgRG91YmxlIGNoZWNrIHlpZWxkIGNhbGN1bGF0aW9uDQoNCmBgYHtyIGZpZy5oZWlnaHQ9NiwgZmlnLndpZHRoPTh9DQpwbGFudHNfdG9faGFydmVzdCA8LSBwbGFudHNfaGFydmVzdGVkICU+JSANCiAgZ2dwbG90KGFlcyh4ID0gZmFjdG9yKG9ic19oYXJ2ZXN0X251bWJlciksIA0KICAgICAgICAgICAgIHkgPSBuLCBmaWxsID0gZmFjdG9yKG9ic19oYXJ2ZXN0X251bWJlcikpKSArDQogIGdlb21fY29sKGNvbCA9ICdibGFjaycpICsNCiAgI3NjYWxlX2ZpbGxfamNvKCkgKw0KICAjdGhlbWVfeGlhb2ZlaSgpICsNCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQodmp1c3QgPSAxLCBhbmdsZSA9IDY1KSwNCiAgICAgICAgdGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMjApLA0KICAgICAgICBsZWdlbmQucG9zaXRpb249InRvcCIpKw0KICBsYWJzKHggPSAiSGFydmVzdF9wbGFudF9udW1iZXIiLCB5ID0gIkZyZXEiLCBmaWxsID0gIkhhcnZlc3RfcGxhbnRfbnVtYmVyIikgKw0KICBmYWNldF93cmFwKH4gdXNlX3RyaWFsX25hbWUpDQoNCnByaW50KHBsYW50c190b19oYXJ2ZXN0KQ0KDQojIGdnc2F2ZShwYXN0ZSgiaW1hZ2VzXFxiYXIiLCB0cmlhbF9pbnRlcmVzdCwgIi5wbmciLCBzZXAgPSAiXyIpLA0KIyAgICAgICAgcGxvdCA9IHBsYW50c190b19oYXJ2ZXN0LCB1bml0cyA9ICJpbiIsIGRwaSA9IDMwMCwgd2lkdGggPSA5LCBoZWlnaHQgPSA2KQ0KYGBgDQoNCiMgQ29tcHV0ZSBnZXJtaW5hdGlvbiwgeWllbGQsIHlpZWxkX3N0YXJjaA0KDQpgYGB7cn0NCnRyaWFsX3N0YW5kYXJkIDwtIHRyaWFsX3N0YW5kYXJkICU+JQ0KICBtdXRhdGUob2JzX2hhcnZlc3RfbnVtYmVyX3BsYW4gPQ0KICAgICAgICAgICBjYXNlX3doZW4oc3RyX2RldGVjdCh1c2VfdHJpYWxfbmFtZSwgIjIwMjMxMTEiKSAgfiA0LA0KICAgICAgICAgICAgICAgICAgICAgc3RyX2RldGVjdCh1c2VfdHJpYWxfbmFtZSwgIjIwMjMxMTIiKSAgfiA0LA0KICAgICAgICAgICAgICAgICAgICAgc3RyX2RldGVjdCh1c2VfdHJpYWxfbmFtZSwgIjIwMjMxMTMiKSAgfiAxMCwNCiAgICAgICAgICAgICAgICAgICAgIHN0cl9kZXRlY3QodXNlX3RyaWFsX25hbWUsICIyMDIzMTE0IikgIH4gMTApLA0KICAgICAgICAgb2JzX2dlcm1pbmF0aW9uX3BlcmMgPSBvYnNfZ2VybWluYXRlZF9udW1iZXJfcGxvdC9vYnNfcGxhbnRlZF9udW1iZXJfcGxvdCAqIDEwMCwNCiAgICAgICAgICMgMikgY2FsY3VsYXRlIGFyZWEgcGVyIHBsYW50DQogICAgICAgICBhcmVhX3BsYW50ID0gKHVzZV9wbG90X2xlbmd0aCp1c2VfcGxvdF93aWR0aCkvb2JzX3BsYW50ZWRfbnVtYmVyX3Bsb3QsDQogICAgICAgICAjIDMpIGNhbGN1bGF0ZSB0aGUgeWllbGRfdjQgb2JzX3BsYW50ZWRfbnVtYmVyX3Bsb3QNCiAgICAgICAgIG9ic195aWVsZF9oYSA9IGlmZWxzZShvYnNfeWllbGRfaGEgPT0gMCwgTkEsIG9ic195aWVsZF9oYSksDQogICAgICAgICBvYnNfc3RhcmNoX2NvbnRlbnQgPSBpZmVsc2Uob2JzX3N0YXJjaF9jb250ZW50ID09IDAsIE5BLCBvYnNfc3RhcmNoX2NvbnRlbnQpLA0KICAgICAgICAgb2JzX3lpZWxkX2hhX3YyID0gKCgob2JzX3Jvb3Rfd2VpZ2h0X3Bsb3QqMTAwMDApLyhhcmVhX3BsYW50Km9ic19oYXJ2ZXN0X251bWJlcl9wbGFuKSkvMTAwMCksDQogICAgICAgICBvYnNfc3RhcmNoX3lpZWxkX2hhID0gb2JzX3N0YXJjaF9jb250ZW50ICogb2JzX3lpZWxkX2hhX3YyIC8gMTAwKQ0KDQpsaWJyYXJ5KHBsb3RseSkNCg0KcDEgPC0gdHJpYWxfc3RhbmRhcmQgJT4lIGdncGxvdCgpICsNCiAgZ2VvbV9wb2ludChhZXMoeCA9IG9ic195aWVsZF9oYSwgeSA9IG9ic195aWVsZF9oYV92MiwgY29sb3IgPSB1c2VfcGxvdF9udW1iZXIpLCBzaG93LmxlZ2VuZCA9IEYpICsNCiAgZmFjZXRfd3JhcCh+dXNlX3RyaWFsX25hbWUpICsNCiAgdGhlbWVfeGlhb2ZlaSgpDQoNCmdncGxvdGx5KHAxKQ0KZGV0YWNoKCJwYWNrYWdlOnBsb3RseSIsIHVubG9hZCA9IFRSVUUpDQpgYGANCg0KIyMgSXMgbnVtZXJpYyBhbGwgdHJhaXRzPw0KDQpgYGB7cn0NCiMjIElzIG51bWVyaWMgYWxsIHRyYWl0cz8NCmlzX251bWVyaWModHJpYWxfZGF0YSA9IHRyaWFsX3N0YW5kYXJkKQ0KDQojIEdldCB0aGUgdGlkeSBkYXRhDQptZXRhX2luZm8gPSBuYW1lcyh0cmlhbF9zdGFuZGFyZCApW3N0cl9kZXRlY3QobmFtZXModHJpYWxfc3RhbmRhcmQpLCAidXNlXyIpXQ0KbWV0YV9pbmZvID0gZ3N1YigidXNlXyIsICIiLCBtZXRhX2luZm8pDQptZXRhX2luZm8NCnRyaWFsX3RpZHkgPSB0cmlhbF9zdGFuZGFyZA0KbmFtZXModHJpYWxfdGlkeSk9IGdzdWIoInVzZV8iLCAiIiwgbmFtZXModHJpYWxfc3RhbmRhcmQpKQ0KDQojIG9ic2VydmF0aW9ucw0KdHJhaXRfbGlzdCA9IG5hbWVzKHRyaWFsX3RpZHkpW3N0cl9kZXRlY3QobmFtZXModHJpYWxfdGlkeSksICJvYnNfIildDQp0cmFpdF9saXN0ID0gZ3N1Yigib2JzXyIsICIiLCB0cmFpdF9saXN0KQ0KdHJhaXRfbGlzdA0KbmFtZXModHJpYWxfdGlkeSk9IGdzdWIoIm9ic18iLCAiIiwgbmFtZXModHJpYWxfdGlkeSkpDQp0cmlhbF90aWR5ID0gdHJpYWxfdGlkeVtjKG1ldGFfaW5mbywgdHJhaXRfbGlzdCldDQpgYGANCg0KIyBCb3hwbG90cw0KDQpgYGB7cn0NCiMgQm94cGxvdHMgYW5kIHNhdmUgaW4gb3V0cHV0IGZvbGRlcg0KZGV2Lm9mZigpDQpib3hwbG90X3RyYWl0cyhteV9kYXQgPSB0cmlhbF90aWR5LA0KICAgICAgICAgICAgICAgdHJhaXRfd2FudGVkID0gdHJhaXRfbGlzdCwNCiAgICAgICAgICAgICAgIGZvbGRlciA9IHBhc3RlMChoZXJlOjpoZXJlKCJvdXRwdXQiKSwgIi8iKSwgDQogICAgICAgICAgICAgICB0cmlhbF9pbnRlcmVzdCkNCg0KDQojIEdyb3VwaW5nIGJveHBsb3QNCnRyYWl0X3dhbnRlZCA8LSB0cmFpdF9saXN0DQpwbG90X2J4cCA8LSB0cmlhbF90aWR5ICU+JQ0KICBwaXZvdF9sb25nZXIoDQogICAgY29scyA9IGFsbF9vZih0cmFpdF93YW50ZWQpLA0KICAgIG5hbWVzX3RvID0gInZhciIsDQogICAgdmFsdWVzX3RvID0gInZhbHVlcyINCiAgKSAlPiUNCiAgZmlsdGVyKCF2YXIgJWluJSBjKA0KICAgICJzdGFrZV9wbGFudCIsICJwbGFudGVkX251bWJlcl9wbG90IiwNCiAgICAiaGFydmVzdF9udW1iZXIiLCAicm9vdF93ZWlnaHRfYWlyIiwNCiAgICAicm9vdF93ZWlnaHRfd2F0ZXIiLCAiaGFydmVzdF9udW1iZXJfcGxhbiIsDQogICAgInJvb3Rfcm90X3BlcmMiLCAieWllbGRfaGFfdjIiDQogICkpICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSB0cmlhbF9uYW1lLCB5ID0gdmFsdWVzKSkgKw0KICBmYWNldF93cmFwKH52YXIsDQogICAgICAgICAgICAgbmNvbCA9IDUsIHNjYWxlcyA9ICJmcmVlX3kiDQogICkgKyANCiAgZ2VvbV92aW9saW4oZmlsbCA9ICJncmF5IikgKw0KICBnZW9tX2JveHBsb3Qod2lkdGggPSAwLjIpICsNCiAgbGFicyh4ID0gTlVMTCwgeSA9IE5VTEwsIHRpdGxlID0gIiIpICsNCiAgdGhlbWVfeGlhb2ZlaSgpICsNCiAgdGhlbWUoDQogICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDgsIHZqdXN0ID0gMSwgYW5nbGUgPSA2NSksDQogICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDgpLA0KICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoY29sb3IgPSAiYmxhY2siKSwNCiAgICBzdHJpcC50ZXh0LnggPSBlbGVtZW50X3RleHQoDQogICAgICBzaXplID0gOCwgZmFjZSA9ICJib2xkLml0YWxpYyIpDQogICkgDQoNCnByaW50KHBsb3RfYnhwKQ0KDQpnZ3NhdmUocGFzdGUwKCJpbWFnZXNcXGJveHBsb3RfIiwgdHJpYWxfaW50ZXJlc3QsICIucG5nIiksDQogICAgICAgcGxvdCA9IHBsb3RfYnhwLCB1bml0cyA9ICJpbiIsIGRwaSA9IDMwMCwgd2lkdGggPSAxNiwgaGVpZ2h0ID0gMTINCikNCmBgYA0KIyBTYXZlIHRoZSB0aWR5IGRhdGEgZm9yIGFuYWx5c2lzDQoNCmBgYHtyfQ0Kd3JpdGUuY3N2KHRyaWFsX3RpZHksIGhlcmU6OmhlcmUoIm91dHB1dCIsIHBhc3RlKCIwMV8iLCB5ZWFyX2ludGVyZXN0LCB0cmlhbF9pbnRlcmVzdCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJfdGlkeV9kYXRhNGFuYWx5c2lzXyIsICIuY3N2Iiwgc2VwID0gIiIpKSwgcm93Lm5hbWVzID0gRkFMU0UpDQpgYGANCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQo=